// Elevator.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <Windows.h>
#include <iostream>
#include <string>
#include "listeners.h"
#include "Passenger.h"
#include "FloorsManager.h"
#include "CmdLineDrawer.h"

#define MODE_AUTO 0
#define MODE_STEP_BY_STEP 1

class CFloorManagerUpdateListener : public IUpdateListener
{
protected:
	CFloorManagerUpdateListener(CFloorsManager& floorsManager) : m_floorsManager(floorsManager) {};
	CFloorsManager& m_floorsManager;
};

class CStepByStepUpdateListener : public CFloorManagerUpdateListener
{
public:
	CStepByStepUpdateListener(CFloorsManager& m) : CFloorManagerUpdateListener(m)
	{}

	virtual void Update()
	{
		//redraw
		m_floorsManager.Redraw();
		std::cout << "Press Enter to continue";
		getchar();
	}
};

class CAutomaticUpdateListener : public CFloorManagerUpdateListener
{
public:
	CAutomaticUpdateListener(CFloorsManager& m) : CFloorManagerUpdateListener(m)
	{}

	void Update()
	{
		m_floorsManager.Redraw();
		Sleep(500);
	}
};

bool TryStrToInt(const std::string& s, size_t& i)
{
	for (size_t ii=0; ii<s.size(); ++ii)
	{
		if (!isdigit(s[ii]))
			return false;
	}

	i = atoi(s.c_str());
	return true;
}

size_t AskNumber()
{
	std::string s;
	while(true)
	{
		std::cin >> s;

		size_t i(100500);
		if (TryStrToInt(s, i))
			return i;
		
		std::cout << "Wrong! Try again" << std::endl;
	}
	
	return -1;
}

int _tmain(int argc, _TCHAR* argv[])
{
	std::cout << "Welcome to 'Discrete elevator' emulating application!" << std::endl;

	std::cout << "Please enter elevator's capacity: ";
	size_t capacity = AskNumber();
	
	std::cout << "Please enter mode automatic{0} or step-by-step{1}: ";
	
	int mode = AskNumber();
	while (mode != MODE_AUTO && mode != MODE_STEP_BY_STEP)
	{
		std::cout << "Please enter 0 or 1: ";
		mode = AskNumber();
	}

	std::cout << "Please enter passengers intencity(per 10 steps): ";
	size_t intencity = AskNumber();

	std::cout << "Please enter steps: ";
	size_t stepsToDo = AskNumber();
	
	CFloorManagerUpdateListener* pListener = NULL;
	CFloorsManager manager(capacity, intencity, stepsToDo, new CCmdLineDrawer()); //starting from first floor
	if(mode == MODE_AUTO)
		pListener = new CAutomaticUpdateListener(manager);
	else
		pListener = new CStepByStepUpdateListener(manager);

	manager.SetUpdateListener(pListener);

	std::cout << "Please enter floors count: ";
	size_t floorsCount = AskNumber();
	manager.GenerateFloors(floorsCount);

	manager.Redraw();

	std::cout << "Press Enter to start.. ";
	getchar();
	getchar();
	manager.Start();

	std::cout << "Press Enter to exit.. ";
	getchar();
	return 0;
}

